package com.ruoyi.law.utils;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.XmlUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.ruoyi.common.utils.sign.Md5Utils;
import com.ruoyi.law.domain.dto.WxUnifiedOrderDTO;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.web.client.RestTemplate;
import org.w3c.dom.Document;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * 订单工具
 *
 * @author lie
 * @date 2022/11/23
 */
public class OrderUtil {

    private static RestTemplate restTemplate = SpringUtil.getBean(RestTemplate.class);

    /**
     * 生成订单号（25位）：时间（精确到毫秒）+3位随机数+5位用户id
     *
     * @param userId 用户id
     * @return {@link String}
     */
    public static synchronized String getOrderNum(Long userId) {
        //时间（精确到毫秒）
        DateTimeFormatter ofPattern = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS");
        String localDate = LocalDateTime.now().format(ofPattern);
        //3位随机数
        String randomNumeric = RandomStringUtils.randomNumeric(3);
        //5位用户id
        int subStrLength = 5;
        String sUserId = userId.toString();
        int length = sUserId.length();
        String str;
        if (length >= subStrLength) {
            str = sUserId.substring(length - subStrLength, length);
        } else {
            str = String.format("%0" + subStrLength + "d", userId);
        }
        return localDate + randomNumeric + str;
    }

    /**
     * 微信统一下单
     *
     * @param wxUnifiedOrderDTO 微信统一下单dto
     * @return {@link String} 返回prepay_id
     */
    public static String unifiedOrder(WxUnifiedOrderDTO wxUnifiedOrderDTO) {
        String unifiedOrderUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder";

        Map<String, String> map = new HashMap<>(10);
        map.put("appid", wxUnifiedOrderDTO.getAppId());
        map.put("openid", wxUnifiedOrderDTO.getOpenId());
        map.put("mch_id", wxUnifiedOrderDTO.getMchId());
        map.put("nonce_str", IdUtil.simpleUUID());
        map.put("body", wxUnifiedOrderDTO.getBody());
        map.put("out_trade_no", wxUnifiedOrderDTO.getOutTradeNo());
        map.put("total_fee", wxUnifiedOrderDTO.getTotalFee().intValue() + "");
        map.put("spbill_create_ip", "123.12.12.123");
        map.put("notify_url", "http://www.baidu.com");
        map.put("trade_type", "JSAPI");

        String sign = getParamStr(map, wxUnifiedOrderDTO.getKey());
        sign = Md5Utils.hash(sign).toUpperCase();
        map.put("sign", sign);

        //map转xml
        Document xml = XmlUtil.mapToXml(map, "xml");
        String resXmlStr = restTemplate.postForObject(unifiedOrderUrl, xml, String.class);
        Map<String, Object> xmlToMap = XmlUtil.xmlToMap(resXmlStr);

        return MapUtil.getStr(xmlToMap, "prepay_id");
    }

    /**
     * 将Map转换为签名字符串
     *
     * @param map map
     * @param key 关键
     * @return {@link String}
     */
    private static String getParamStr(Map<String, String> map, String key) {
        Set<String> keySet = map.keySet();
        String[] keyArray = keySet.toArray(new String[0]);
        Arrays.sort(keyArray);
        StringBuilder sb = new StringBuilder();
        //将除sign的其他非空参数按照ASCII码排序，并拼接位URL键值对形式的字符串
        for (String k : keyArray) {
            //遇到sign参数跳过不处理
            if ("sign".equals(k)) {
                continue;
            }
            // 参数值为空，则不参与签名
            if (map.get(k).trim().length() > 0) {
                sb.append(k).append("=").append(map.get(k).trim()).append("&");
            }
        }
        //结尾拼接key
        sb.append("key=").append(key);
        return sb.toString();
    }
}
